const Joi = require('joi');
const logger = require('../utils/logger');

/**
 * 验证请求数据的中间件
 * @param {object} schema - Joi验证模式
 * @returns {function} Express中间件函数
 */
const validateRequest = (schema) => {
  return (req, res, next) => {
    try {
      // 构建验证对象
      const dataToValidate = {};
      
      // 根据请求方法选择验证数据
      if (req.method === 'GET') {
        dataToValidate.query = req.query;
        dataToValidate.params = req.params;
      } else {
        dataToValidate.body = req.body;
        dataToValidate.params = req.params;
        dataToValidate.query = req.query;
      }

      // 创建Joi验证模式
      const joiSchema = Joi.object().keys(schema);
      
      // 执行验证
      const { error, value } = joiSchema.validate(dataToValidate, {
        abortEarly: false,
        stripUnknown: true,
        allowUnknown: false
      });

      if (error) {
        // 格式化验证错误
        const validationErrors = error.details.map(detail => ({
          field: detail.path.join('.'),
          message: detail.message,
          type: detail.type
        }));

        logger.warn('请求验证失败', {
          method: req.method,
          url: req.url,
          errors: validationErrors
        });

        return res.status(400).json({
          success: false,
          error: '请求数据验证失败',
          details: validationErrors,
          timestamp: new Date().toISOString()
        });
      }

      // 验证通过，将验证后的数据赋值回请求对象
      if (value.body) req.body = value.body;
      if (value.query) req.query = value.query;
      if (value.params) req.params = value.params;

      next();
    } catch (err) {
      logger.error('验证中间件执行错误', { error: err.message });
      return res.status(500).json({
        success: false,
        error: '验证中间件执行错误',
        message: err.message,
        timestamp: new Date().toISOString()
      });
    }
  };
};

/**
 * 验证股票代码格式
 * @param {string} symbol - 股票代码
 * @returns {boolean} 是否有效
 */
const validateStockSymbol = (symbol) => {
  const symbolSchema = Joi.string()
    .pattern(/^[A-Z]{1,5}$/)
    .min(1)
    .max(5)
    .required();

  const { error } = symbolSchema.validate(symbol);
  return !error;
};

/**
 * 验证日期格式
 * @param {string} date - 日期字符串
 * @returns {boolean} 是否有效
 */
const validateDate = (date) => {
  const dateSchema = Joi.date().iso().required();
  const { error } = dateSchema.validate(date);
  return !error;
};

/**
 * 验证分页参数
 * @param {object} pagination - 分页参数
 * @returns {object} 验证后的分页参数
 */
const validatePagination = (pagination) => {
  const paginationSchema = Joi.object({
    page: Joi.number().integer().min(1).default(1),
    limit: Joi.number().integer().min(1).max(100).default(20),
    sortBy: Joi.string().valid('asc', 'desc').default('desc'),
    sortField: Joi.string().default('createdAt')
  });

  const { value, error } = paginationSchema.validate(pagination);
  if (error) {
    throw new Error('分页参数验证失败');
  }

  return value;
};

/**
 * 验证时间范围
 * @param {object} timeRange - 时间范围参数
 * @returns {object} 验证后的时间范围
 */
const validateTimeRange = (timeRange) => {
  const timeRangeSchema = Joi.object({
    startDate: Joi.date().iso().required(),
    endDate: Joi.date().iso().min(Joi.ref('startDate')).required(),
    timezone: Joi.string().default('UTC')
  });

  const { value, error } = timeRangeSchema.validate(timeRange);
  if (error) {
    throw new Error('时间范围参数验证失败');
  }

  return value;
};

module.exports = {
  validateRequest,
  validateStockSymbol,
  validateDate,
  validatePagination,
  validateTimeRange
};
